//
// Created by root on 4/29/17.
//

#include "../runner_scheme.h"

#define OP_CHARACTER(_op,_char) Cell* c = make_character(global_scheme, _char); \
    global_scheme->args = cons(global_scheme, c, &g_nil); \
    op_## _op \
    (global_scheme); \
    Cell* r = global_scheme->returnValue

#define OP_CHARACTER_FAILURE(_op) c = make_string(global_scheme, "a"); \
    global_scheme->args = cons(global_scheme, c, &g_nil); \
    op_## _op \
    (global_scheme); \
    r = global_scheme->returnValue; \
    assert_string_equal(r->_type, EXCEPTION_TYPE); \
    assert_string_equal(car(r)->_string, "INVALID_TYPE");

static void test_op_make_character_case1() {
    Cell* c = make_character(global_scheme, 'a');
    assert_string_equal(c->_type, CHARACTER_TYPE);
    assert_int_equal(c->_longValue, 'a');
}

static void test_op_make_character_case2() {
    Cell* c = make_character(global_scheme, '\n');
    assert_string_equal(c->_type, CHARACTER_TYPE);
    assert_int_equal(c->_longValue, '\n');
}

static void test_op_char_to_integer_case1() {
    OP_CHARACTER(char_to_integer, '0');
    assert_string_equal(r->_type, INTEGER_TYPE);
    assert_int_equal(r->_longValue, 0);
}

static void test_op_char_to_integer_case2() {
    OP_CHARACTER(char_to_integer, 'a');
    assert_string_equal(r->_type, INTEGER_TYPE);
    assert_int_equal(r->_longValue, 10);
}

static void test_op_char_to_integer_case3() {
    OP_CHARACTER(char_to_integer, 'F');
    assert_string_equal(r->_type, INTEGER_TYPE);
    assert_int_equal(r->_longValue, 15);
}

static void test_op_char_to_integer_case4() {
    OP_CHARACTER(char_to_integer, 'g');
    assert_string_equal(r->_type, EXCEPTION_TYPE);
    assert_string_equal(car(r)->_string, "NOT_DIGIT");
}

static void test_op_char_to_string_case1() {
    OP_CHARACTER(char_to_string, 'a');
    assert_string_equal(r->_type, STRING_TYPE);
    assert_string_equal(r->_string, "a");
}

static void test_op_char_to_string_case2() {
    OP_CHARACTER(char_to_string, '\n');
    assert_string_equal(r->_type, STRING_TYPE);
    assert_string_equal(r->_string, "\n");
}

static void test_op_charap_case1() {
    OP_CHARACTER(charap, 'a');
    assert_ptr_equal(r, &g_true);
}

static void test_op_charap_case2() {
    OP_CHARACTER(charap, '0');
    assert_ptr_equal(r, &g_false);
}

static void test_op_charnp_case1() {
    OP_CHARACTER(charnp, 'a');
    assert_ptr_equal(r, &g_false);
}

static void test_op_charnp_case2() {
    OP_CHARACTER(charnp, '0');
    assert_ptr_equal(r, &g_true);
}

static void test_op_charwp_case1() {
    OP_CHARACTER(charwp, ' ');
    assert_ptr_equal(r, &g_true);
}

static void test_op_charwp_case2() {
    OP_CHARACTER(charwp, '\n');
    assert_ptr_equal(r, &g_true);
}

static void test_op_charwp_case3() {
    OP_CHARACTER(charwp, '\t');
    assert_ptr_equal(r, &g_true);
}

static void test_op_charwp_case4() {
    OP_CHARACTER(charwp, 'a');
    assert_ptr_equal(r, &g_false);
}

static void test_op_charup_case1() {
    OP_CHARACTER(charup, 'A');
    assert_ptr_equal(r, &g_true);
}

static void test_op_charup_case2() {
    OP_CHARACTER(charup, 'a');
    assert_ptr_equal(r, &g_false);
}

static void test_op_charlp_case1() {
    OP_CHARACTER(charlp, 'a');
    assert_ptr_equal(r, &g_true);
}

static void test_op_charlp_case2() {
    OP_CHARACTER(charlp, 'A');
    assert_ptr_equal(r, &g_false);
}

static void test_op_char_upcase() {
    OP_CHARACTER(char_upcase, 'a');
    assert_string_equal(r->_type, CHARACTER_TYPE);
    assert_int_equal(r->_longValue, 'A');
}

static void test_op_char_downcase() {
    OP_CHARACTER(char_downcase, 'A');
    assert_string_equal(r->_type, CHARACTER_TYPE);
    assert_int_equal(r->_longValue, 'a');
}

static void test_op_character_failure() {
    Cell* c;
    Cell* r;
    OP_CHARACTER_FAILURE(char_to_integer);
    OP_CHARACTER_FAILURE(charap);
    OP_CHARACTER_FAILURE(charwp);
    OP_CHARACTER_FAILURE(charup);
    OP_CHARACTER_FAILURE(charlp);
    OP_CHARACTER_FAILURE(char_upcase);
    OP_CHARACTER_FAILURE(char_downcase);
}

int main(int argc, char **argv) {
    const struct CMUnitTest tests[] = {
            cmocka_unit_test(test_op_make_character_case1),
            cmocka_unit_test(test_op_make_character_case2),
            cmocka_unit_test(test_op_char_to_integer_case1),
            cmocka_unit_test(test_op_char_to_integer_case2),
            cmocka_unit_test(test_op_char_to_integer_case3),
            cmocka_unit_test(test_op_char_to_integer_case4),
            cmocka_unit_test(test_op_char_to_string_case1),
            cmocka_unit_test(test_op_char_to_string_case2),
            cmocka_unit_test(test_op_charap_case1),
            cmocka_unit_test(test_op_charap_case2),
            cmocka_unit_test(test_op_charnp_case1),
            cmocka_unit_test(test_op_charnp_case2),
            cmocka_unit_test(test_op_charwp_case1),
            cmocka_unit_test(test_op_charwp_case2),
            cmocka_unit_test(test_op_charwp_case3),
            cmocka_unit_test(test_op_charwp_case4),
            cmocka_unit_test(test_op_charup_case1),
            cmocka_unit_test(test_op_charup_case2),
            cmocka_unit_test(test_op_charlp_case1),
            cmocka_unit_test(test_op_charlp_case2),
            cmocka_unit_test(test_op_char_upcase),
            cmocka_unit_test(test_op_char_downcase),
            cmocka_unit_test(test_op_character_failure),
    };
    return cmocka_run_group_tests(tests, setup_scheme, teardown_scheme);
}
